package com.zhangbo.share.baffle;

import com.alibaba.fastjson.JSONObject;
import com.zhangbo.share.annotation.DataBaffle;
import com.zhangbo.share.api.IDataBaffleApi;
import com.zhangbo.share.bean.BaffleBean;
import com.zhangbo.share.bean.BaffleRule;
import com.zhangbo.share.bean.DataBaffleBean;
import com.zhangbo.share.util.AopUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author zhangbo
 * @version 1.00
 * @classdesc <pre>数据挡板功能</pre>
 * @create 2021/11/5 14:49
 * @update <pre>
 *     版本           修改人         修改日期         修改内容描述
 *     -----------------------------------------------------------
 *     1.00           zhangbo     2021/11/5 14:49
 *     -----------------------------------------------------------
 * </pre>
 */
@Slf4j
@Aspect
@Component
@ConditionalOnProperty(prefix = "share.data", name = "baffle", havingValue = "true")
public class DataBaffleAspect {

    @Autowired
    private IDataBaffleApi dataBaffleApi;

    @Pointcut("@annotation(com.zhangbo.share.annotation.DataBaffle)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = AopUtils.resolveMethod(joinPoint);
        DataBaffle annotation = method.getAnnotation(DataBaffle.class);
        String group = annotation.group();
        String code = annotation.code();
        DataBaffleBean dataBaffleBean = dataBaffleApi.dataBaffleResponse(group, code);


        if (null == dataBaffleBean) {
            //未配置挡板，继续接口调用
            return joinPoint.proceed();
        } else if (null == dataBaffleBean.getBaffleBean() || dataBaffleBean.getBaffleBean().isEmpty()) {
            Class<?> currentReturnType = method.getReturnType();
            if (currentReturnType.equals(List.class) && method.getGenericReturnType() instanceof ParameterizedType) {
                //获取返回值，区分list和其它。暂时只支持一层泛型
                Type returnType = method.getGenericReturnType();
                Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
                Class<?> actualType = (Class<?>) actualTypeArguments[0];
                return JSONObject.parseArray(dataBaffleBean.getResult(), actualType);
            }
            return JSONObject.parseObject(dataBaffleBean.getResult(), currentReturnType);
        } else {
            Class<?> currentReturnType = method.getReturnType();
            //返回的为List类型
            String result = generateResult(joinPoint, dataBaffleBean);
            log.info("构建生成挡板数据：{}", result);
            if (currentReturnType.equals(List.class) && method.getGenericReturnType() instanceof ParameterizedType) {
                Type returnType = method.getGenericReturnType();
                Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
                Class<?> actualType = (Class<?>) actualTypeArguments[0];
                return JSONObject.parseArray(result, actualType);
            }
            return JSONObject.parseObject(result, currentReturnType);
        }
    }

    private String generateResult(ProceedingJoinPoint joinPoint, DataBaffleBean dataBaffleBean) {
        JSONObject param = null;
        String result = dataBaffleBean.getResult();
        for (BaffleBean baffleBean : dataBaffleBean.getBaffleBean()) {
            String type = baffleBean.getType();
            String paramName = baffleBean.getParamName();
            BaffleRule baffleRule = baffleBean.getBaffleRule();
            Object value = null;
            if (DataBaffleEnums.BaffleTypeEnum.ID.getValue().equals(type)) {
                value = DataBaffleUtil.generateId(baffleRule);
            } else if (DataBaffleEnums.BaffleTypeEnum.PARAM.getValue().equals(type)) {
                if (param == null) {
                    try {
                        Object[] args = joinPoint.getArgs();
                        if (null != args) {
                            param = JSONObject.parseObject(JSONObject.toJSONString(args[0]));
                        }
                    } catch (Exception e) {
                        log.error("挡板获取入参错误：{}", e);
                    }
                }
                if (param != null) {
                    value = DataBaffleUtil.generateParam(param, baffleRule);
                }
            } else if (DataBaffleEnums.BaffleTypeEnum.ENUM.getValue().equals(type)) {
                value = DataBaffleUtil.generateEnum(baffleRule);
            } else if (DataBaffleEnums.BaffleTypeEnum.DATE.getValue().equals(type)) {
                value = DataBaffleUtil.generateDate(baffleRule);
            }
            result = result.replaceAll("\\{" + paramName + "}", String.valueOf(value));
        }
        return result;
    }


}
